<?php
/**
 * Шаблонизатор SQL запроса из конструктора
 * Тут всё скучно. Методы парсят данные и возвращают фрагменты кода SQL, который потом соберется в единую строку.
 */
class SqlProcessor {

    private $queryTemplate = array(
        'select' => 'SELECT @option: @field: FROM @table: @cond: @group: @order: @limit:',
        'insert' => 'INSERT INTO @table: (@field:) @values:',
        'delete' => 'DELETE FROM @table: @cond: @limit:',
        'update' => 'UPDATE @table: @set: @cond: @limit:',
        'native' => '@query:',
    );
    private $logic = array(
        -1 => 'NOT',
        0 => 'AND',
        1 => 'OR',
    );
    private $cond = array(
        -5 => 'NOT BETWEEN',
        -4 => 'NOT IN',
        -3 => 'NOT LIKE',
        -2 => '<',
        -1 => '<=',
        0 => '=',
        1 => '>=',
        2 => '>',
        3 => 'LIKE',
        4 => 'IN',
        5 => 'BETWEEN',
    );

    public function __call($name, $arguments) {
        if (method_exists(__CLASS__, $name)) {
            return $this->$name($arguments);
        } else {
            return "/* " . __CLASS__ . "::$name */";
        }
    }

    function query($data) {
        return $data;
    }
    function action($data) {
        return $this->queryTemplate[$data];
    }
    
    function option($options) {
        return implode(' ', $options);
    }
    
    function limit($data) {
        return "limit ".implode(', ', $data);
    }
    
    function order($data) {
        $pieces = array();
        foreach ($data as $record) {
            $pieces[] = $record['field']." ".$record['direction'];
        }
        return "order by ".implode(', ', $pieces);
    }
    
    function values($values) {
        $pieces = array();
        
        foreach ($values as $record) {
            foreach($record as $i => $rec){
                if($rec == "NULL()"){
                    $record[$i] = 'NULL';
                }elseif(is_numeric($rec)){
                    $record[$i] = $rec;
                }elseif(is_string($rec)){
                    $record[$i] = "'$rec'";
                }elseif($rec == ""){
                    $record[$i] = "''";
                }
            }
            $pieces[] = "(".implode(", ", $record).")";
        }
        return "VALUES ".implode(', ', $pieces);
    }

    function table($data) {
        $pieces = array();
        foreach ($data as $record) {
            $pieces[] = $record['name'] . ($record['alias'] ? " as " . $record['alias'] : false);
        }
        return implode(", ", $pieces);
    }

    function field(&$data) {
        return $this->table($data);
    }

    function cond($data) {
        $pieces = array();
        foreach ($data as $index => $params) {
            $params['logic'] = $index == 0 ? "WHERE" : $this->logic[$params['logic']];
            $params['value'] = ($params['noquotes'] || is_numeric($params['value'])) ? $params['value'] : "'" . $params['value'] . "'";
            $pieces[] = $params['logic'] . " " . $params['field'] . " " . $this->cond[$params['cond']] . " " . $params['value'];
        }
        return implode(" ", $pieces);
    }
    
    function set($data) {
        $pieces = array();
        foreach ($data as $params) {
            $params['value'] = ($params['noquotes'] || is_numeric($params['value'])) ? $params['value'] : "'" . $params['value'] . "'";
            if($params['value'] == "'NULL()'"){
                $params['value'] = 'NULL';
            }
            $pieces[] = $params['field'] . " = " . $params['value'];
        }
        return "SET ".implode(", ", $pieces);
    }

}
